package com.rolerealm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rolerealm.common.constant.ErrorCode;
import com.rolerealm.common.exception.BusinessException;
import com.rolerealm.common.util.JwtUtil;
import com.rolerealm.dao.UserMapper;
import com.rolerealm.domain.dto.UserLoginRequest;
import com.rolerealm.domain.dto.UserRegisterRequest;
import com.rolerealm.domain.entity.UserEntity;
import com.rolerealm.domain.vo.LoginResponseVO;
import com.rolerealm.domain.vo.UserInfoVO;
import com.rolerealm.domain.vo.UserSimpleVO;
import com.rolerealm.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.time.format.DateTimeFormatter;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final JwtUtil jwtUtil;
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public UserSimpleVO register(UserRegisterRequest req) {
        if (!StringUtils.hasText(req.getEmail()) && !StringUtils.hasText(req.getPhone())) {
            throw new BusinessException(ErrorCode.PARAM_INVALID);
        }

        // 唯一性校验
        LambdaQueryWrapper<UserEntity> uniqueWrapper = new LambdaQueryWrapper<>();
        uniqueWrapper.eq(UserEntity::getUsername, req.getUsername())
                .or(w -> w.eq(StringUtils.hasText(req.getEmail()), UserEntity::getEmail, req.getEmail()))
                .or(w -> w.eq(StringUtils.hasText(req.getPhone()), UserEntity::getPhone, req.getPhone()));
        Long count = userMapper.selectCount(uniqueWrapper);
        if (count != null && count > 0) {
            throw new BusinessException(ErrorCode.USER_ALREADY_EXISTS);
        }

        UserEntity entity = new UserEntity();
        entity.setUsername(req.getUsername());
        entity.setEmail(req.getEmail());
        entity.setPhone(req.getPhone());
        entity.setPasswordHash(passwordEncoder.encode(req.getPassword()));
        entity.setNickname(req.getNickname());
        entity.setAvatarUrl(req.getAvatarUrl());
        entity.setStatus(1);

        int rows = userMapper.insert(entity);
        if (rows <= 0 || entity.getId() == null) {
            throw new BusinessException(ErrorCode.USER_REGISTER_FAILED);
        }

        UserSimpleVO vo = new UserSimpleVO();
        vo.setUserId(entity.getId());
        vo.setUsername(entity.getUsername());
        return vo;
    }

    @Override
    public LoginResponseVO login(UserLoginRequest req) {
        String principal = req.getPrincipal();

        UserEntity user = userMapper.selectOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUsername, principal)
                .or(w -> w.eq(UserEntity::getEmail, principal))
                .or(w -> w.eq(UserEntity::getPhone, principal))
                .last("limit 1"));

        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        if (!passwordEncoder.matches(req.getPassword(), user.getPasswordHash())) {
            throw new BusinessException(ErrorCode.USER_PASSWORD_ERROR);
        }
        if (Objects.equals(user.getStatus(), 0)) {
            throw new BusinessException(ErrorCode.USER_ACCOUNT_DISABLED);
        }

        String token = jwtUtil.generateToken(user.getId(), user.getUsername(), null);

        LoginResponseVO resp = new LoginResponseVO();
        resp.setToken(token);
        resp.setExpiresIn(604800L); // 7 days in seconds (matching application.yml config)
        LoginResponseVO.UserBasicVO ub = new LoginResponseVO.UserBasicVO();
        ub.setId(user.getId());
        ub.setUsername(user.getUsername());
        ub.setNickname(user.getNickname());
        ub.setAvatarUrl(user.getAvatarUrl());
        resp.setUser(ub);
        return resp;
    }

    @Override
    public UserInfoVO getCurrentUser(Long userId) {
        if (userId == null) {
            throw new BusinessException(ErrorCode.UNAUTHORIZED);
        }
        UserEntity user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        UserInfoVO vo = new UserInfoVO();
        vo.setId(user.getId());
        vo.setUsername(user.getUsername());
        vo.setEmail(user.getEmail());
        vo.setPhone(user.getPhone());
        vo.setNickname(user.getNickname());
        vo.setAvatarUrl(user.getAvatarUrl());
        vo.setStatus(user.getStatus());
        if (user.getCreatedAt() != null) {
            vo.setCreatedAt(user.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }
        return vo;
    }
}


